package com.winchain.chainbill.bill.biz.receive.rx;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.shell.bee.acct.transaction.po.AcctTxRec;
import com.shell.bee.persistence.transaction.Transaction;
import com.shell.bee.persistence.transaction.TransactionUtil;
import com.shell.framework.command.ChainBase;
import com.shell.framework.command.CommandContext;
import com.shell.framework.rx.OnErrorNotImplementedSubscriber;
import com.winchain.chainbill.bill.base.po.CbOpt;
import com.winchain.chainbill.bill.base.po.CbRcv;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.po.CbXfe;
import com.winchain.chainbill.bill.base.service.CbXfeService;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.contract.cmd.ContractCancelCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillHldrCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillRcvAndXfeMoveCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillRcvCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillRcvDfrlCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillRcvRjctCrdtCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillRcvRjctMsgCmd;
import com.winchain.chainbill.bill.biz.receive.cmd.BillXfeRejCertCmd;
import com.winchain.chainbill.bill.biz.receive.vo.BillRcv;
import com.winchain.chainbill.bill.biz.send.cmd.BillInvoiceRejectCmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillMoveCmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillOptCmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillSndInvoinceRejectICmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillTimeoutCmd;
import com.winchain.chainbill.bill.biz.send.rx.BatchBillEvent;
import com.winchain.chainbill.bill.biz.send.vo.BatchBillStats;
import com.winchain.chainbill.bill.biz.transfer.cmd.BillRcv4PrntCmd;
import com.winchain.chainbill.chain.callback.cmd.SyncConfirmCmd;

@Component
public class BillRcvDenySubscriber extends OnErrorNotImplementedSubscriber<BatchBillEvent<BillRcv, CbRcv>> {
	private final Log logger = LogFactory.getLog(getClass());
	@Autowired
	private BillTimeoutCmd<CbRcv> billTimeoutCmd;
	@Autowired
	private BillOptCmd<CbRcv> billOptCmd;
	@Autowired
	private BillMoveCmd<CbRcv> billMoveCmd;
	@Autowired
	private BillRcvRjctCrdtCmd billRcvRjctCrdtCmd;
	@Autowired
	private BillRcvDfrlCmd<CbRcv> billDfrlCmd;
	@Autowired
	private BillHldrCmd<CbRcv> billHldrCmd;
	@Autowired
	private BillRcv4PrntCmd<CbRcv> billInput4PrntCmd;
	@Autowired
	private BillRcvCmd billInputCmd;
	@Autowired
	private BillRcvAndXfeMoveCmd billInputAndXfeMoveCmd;
	@Autowired
	private BillRcvRjctMsgCmd billRcvRjctMsgCmd;
	@Autowired
	private SyncConfirmCmd<Bill<CbRcv>> syncConfirmCmd;
	@Autowired
	private CbXfeService cbXfeService;
	@Autowired
	private ContractCancelCmd<CbRcv> contractCancelCmd;
	@Autowired
	private BillXfeRejCertCmd billXfeRejCertCmd;
	@Autowired
	private BillSndInvoinceRejectICmd<CbRcv> billSndInvoinceRejectICmd;
	@Autowired
	private BillInvoiceRejectCmd billInvoiceRejectCmd;

	public void onApplicationEvent(final BatchBillEvent<BillRcv, CbRcv> t) {
		List<BillRcv> records = t.getRecs();
		BatchBillStats<CbRcv> stats = t.getStats();
		final Bill<CbRcv> bill = new Bill();

		final List<AcctTxRec> AcctTxRecs = new ArrayList();
		for (final BillRcv record : records) {
			try {
				TransactionUtil.execute(new Transaction() {
					public void doInTransaction() {
						Object exp = t.getValue("exp");

						CbRec rcd = record.getRec();
						bill.setRec(rcd);
						CbRcv cbRcv = record.getRcv();

						cbRcv.setRcvState("-1");

						bill.setSource(cbRcv);

						String bizType = (String) t.getValue("bizType");
						CbOpt opt = t.getOperation();
						if ("1".equals(cbRcv.getTxType())) {
							opt.setOptCode("EX13");
							((CbRcv) bill.getSource()).setRcvState("2");
						}
						CommandContext<Bill<CbRcv>> context = new CommandContext();
						context.setSource(bill);
						context.setValue("Operation", opt);
						context.setValue("bizType", bizType);
						context.setValue("exp", exp);

						ChainBase<Bill<CbRcv>> crb = new ChainBase();
						crb.add(BillRcvDenySubscriber.this.billTimeoutCmd);
						crb.add(BillRcvDenySubscriber.this.billOptCmd);

						crb.add(BillRcvDenySubscriber.this.billDfrlCmd);
						String txType = cbRcv.getTxType();
						if ("1".equals(txType)) {
							CbXfe cbXfe = new CbXfe();
							cbXfe = (CbXfe) BillRcvDenySubscriber.this.cbXfeService.selectByKey(cbRcv.getTxId());
							if (!cbXfe.getBillId().equals(cbXfe.getPrntId())) {
								context.setValue("OwnerId", cbRcv.getBuyerId());
								context.setValue("OwnerName", cbRcv.getBuyerNm());

								int level = rcd.getHldrLvl().intValue() - 1;
								rcd.setHldrLvl(Integer.valueOf(level));
								crb.add(BillRcvDenySubscriber.this.billHldrCmd);

								crb.add(BillRcvDenySubscriber.this.billInput4PrntCmd);
							}
							crb.add(BillRcvDenySubscriber.this.billXfeRejCertCmd);

							crb.add(BillRcvDenySubscriber.this.billInputAndXfeMoveCmd);
							crb.add(BillRcvDenySubscriber.this.billInputCmd);

							context.setValue("invType", "3");
							context.setValue("bizId", cbRcv.getTxId());
							crb.add(BillRcvDenySubscriber.this.billInvoiceRejectCmd);
						}
						crb.add(BillRcvDenySubscriber.this.billRcvRjctCrdtCmd);
						crb.add(BillRcvDenySubscriber.this.contractCancelCmd);
						crb.add(BillRcvDenySubscriber.this.billRcvRjctMsgCmd);
						crb.add(BillRcvDenySubscriber.this.billMoveCmd);
						if ("0".equals(txType)) {
							crb.add(BillRcvDenySubscriber.this.billSndInvoinceRejectICmd);
							crb.add(BillRcvDenySubscriber.this.syncConfirmCmd);
						}
						crb.execute(context);

						AcctTxRecs.add((AcctTxRec) context.getValue("acctTxRec"));
					}
				}, new int[0]);

				t.setValue("acctTxRecs", AcctTxRecs);
				stats.addPassedRecord(bill);
			} catch (Exception e) {
				e.printStackTrace();
				this.logger.error("Rcv deny error!", e);
				stats.addAbnormalRecord(bill);
				stats.addAbnormalMsg(e.getMessage());
			}
		}
	}
}
